﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Infrastructure.Data.Core;
using Cesave.Domain.PermisosModule.Contracts.Cultivos;
using Cesave.Infrastructure.Data.PermisosModule.Context;
using Cesave.Infrastructure.CrossCutting.Logging;
using System.Globalization;
using Cesave.Infrastructure.Data.PermisosModule.Resources;
using Cesave.Domain.Core.Specification;
using Cesave.Domain.PermisosModule.Contracts.CultivosFechas;
using Cesave.Domain.PermisosModule.Contracts.CiclosFechas;

namespace Cesave.Infrastructure.Data.PermisosModule.Repositories
{
	public class CultivoRepository
		: GenericRepositoryEx<Cultivo>, ICultivoRepository
	{
		#region Constructor

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="traceManager"></param>
		public CultivoRepository(IPermisosModuleContext context, ITraceManager traceManager)
			: base(context, traceManager)
		{
		}

		#endregion

		#region ICultivoRepository Members

		/// <summary>
		/// 
		/// </summary>
		/// <param name="specification"></param>
		/// <returns></returns>
		public IEnumerable<Cultivo> FindCultivosByClasificacion(CultivosByClasificacionSpecification specification)
		{
			if (specification == null)
				throw new ArgumentNullException("specification");
			return GetBySpec(specification).OrderBy(c => c.Nombre);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="specification"></param>
		/// <returns></returns>
		public IEnumerable<Cultivo> FindCultivosByEstacion(CultivosByEstacionSpecification specification)
		{
			if (specification == null)
				throw new ArgumentNullException("specification");
			return GetBySpec(specification).OrderBy(c => c.Nombre);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="specification"></param>
		/// <returns></returns>
		public IEnumerable<Cultivo> FindCultivosByStatus(CultivosByStatusSpecification specification)
		{
			if (specification == null)
				throw new ArgumentNullException("specification");
			return GetBySpec(specification).OrderBy(c => c.Nombre);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="statusSpecification"></param>
		/// <param name="cicloSpecification"></param>
		/// <param name="juntaSpecification"></param>
		/// <param name="dateSpecification"></param>
		/// <returns></returns>
		public IEnumerable<Cultivo> FindCultivosForExpedicion(
			CultivosByStatusSpecification statusSpecification,
			CiclosFechasByCicloSpecification cicloSpecification,
			CultivosFechasByJuntaSpecification juntaSpecification,
			CiclosFechasByDateRangeSpecification dateSpecification
		)
		{
			IPermisosModuleContext actualContext = StoreContext as IPermisosModuleContext;
			Specification<CiclosFecha> fechasSpecification = new TrueSpecification<CiclosFecha>();
			fechasSpecification &= cicloSpecification;
			fechasSpecification &= dateSpecification;
			if (actualContext != null)
			{
				var cultivos = actualContext.Cultivos.Where(statusSpecification.SatisfiedBy());
				var cultivosFechas = actualContext.CultivosFechas.Where(juntaSpecification.SatisfiedBy());
				var ciclosFechas = actualContext.CiclosFechas.Where(cicloSpecification.SatisfiedBy()).Where(fechasSpecification.SatisfiedBy());
				return from cultivo in cultivos
					   join cultivosFecha in cultivosFechas on cultivo.CultivoGuid equals cultivosFecha.CultivoGuid
					   join fecha in ciclosFechas on new
					   {
						   cultivosFecha.CicloGuid,
						   cultivosFecha.JuntaGuid
					   } equals new
					   {
						   fecha.CicloGuid,
						   fecha.JuntaGuid
					   }
					   orderby cultivo.Nombre
					   group cultivo by cultivo into cs
					   select cs.Key;
			}
			else
				throw new InvalidOperationException(
					string.Format(
						CultureInfo.InvariantCulture,
						Messages.exception_InvalidStoreContext,
						GetType().Name
					)
				);
		}

		#endregion
	}
}
